IPython: beyond plain Python

When executing code in IPython, all valid Python syntax works as-is, but IPython provides a number of features designed to make the interactive experience more fluid and efficient.

First things first: running code, getting help

In the notebook, to run a cell of code, hit Shift-Enter. This executes the cell and puts the cursor in the next cell below, or makes a new one if you are at the end. Alternately, you can use:

  • Alt-Enter to force the creation of a new cell unconditionally (useful when inserting new content in the middle of an existing notebook).
  • Control-Enter executes the cell and keeps the cursor in the same cell, useful for quick experimentation of snippets that you don't need to keep permanently.

In [1]:
print("Hi")


Hi

Getting help:


In [2]:
?

Typing object_name? will print all sorts of details about any object, including docstrings, function definition lines (for call arguments) and constructor details for classes.


In [3]:
import collections
collections.namedtuple?

In [4]:
collections.Counter??

In [5]:
*int*?

An IPython quick reference card:


In [6]:
%quickref

Tab completion

Tab completion, especially for attributes, is a convenient way to explore the structure of any object you’re dealing with. Simply type object_name.<TAB> to view the object’s attributes. Besides Python objects and keywords, tab completion also works on file and directory names.


In [ ]:
collections.

The interactive workflow: input, output, history


In [7]:
2+10


Out[7]:
12

In [8]:
_+10


Out[8]:
22

You can suppress the storage and rendering of output if you append ; to the last cell (this comes in handy when plotting with matplotlib, for example):


In [9]:
10+20;

In [10]:
_


Out[10]:
22

The output is stored in _N and Out[N] variables:


In [11]:
_10 == Out[10]


Out[11]:
True

And the last three have shorthands for convenience:


In [12]:
print('last output:', _)
print('next one   :', __)
print('and next   :', ___)


last output: True
next one   : 22
and next   : 22

In [13]:
In[11]


Out[13]:
'_10 == Out[10]'

In [14]:
_i


Out[14]:
'In[11]'

In [15]:
_ii


Out[15]:
'In[11]'

In [16]:
print('last input:', _i)
print('next one  :', _ii)
print('and next  :', _iii)


last input: _ii
next one  : _i
and next  : In[11]

In [17]:
%history -n 1-5


   1: print("Hi")
   2: ?
   3:
import collections
collections.namedtuple?
   4: collections.Counter??
   5: *int*?

Exercise

Write the last 10 lines of history to a file named log.py.

Accessing the underlying operating system


In [18]:
!pwd


/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel

In [19]:
files = !ls
print("My current directory's files:")
print(files)


My current directory's files:
['Animations Using clear_output.ipynb', 'Background Jobs.ipynb', 'Beyond Plain Python.ipynb', 'Capturing Output.ipynb', 'Cell Magics.ipynb', 'Custom Display Logic.ipynb', 'data', 'example-demo.py', 'gui', 'Index.ipynb', 'ipython-completion.bash', 'ipython.desktop', 'ipython-get-history.py', 'ipython-qtconsole.desktop', 'Old Custom Display Logic.ipynb', 'Plotting in the Notebook.ipynb', 'Raw Input in the Notebook.ipynb', 'Rich Output.ipynb', 'Script Magics.ipynb', 'SymPy.ipynb', 'Terminal Usage.ipynb', 'Third Party Rich Output.ipynb', 'Trapezoid Rule.ipynb', 'Working With External Code.ipynb']

In [21]:
!echo {files[0].upper()}


BACKGROUNDJOBS.IPYNB

Note that all this is available even in multiline blocks:


In [21]:
import os
for i,f in enumerate(files):
    if f.endswith('ipynb'):
        !echo {"%02d" % i} - "{os.path.splitext(f)[0]}"
    else:
        print('--')


00 - Animations Using clear_output
01 - Background Jobs
02 - Beyond Plain Python
03 - Capturing Output
04 - Cell Magics
05 - Custom Display Logic
--
--
--
09 - Index
--
--
--
--
14 - Old Custom Display Logic
15 - Plotting in the Notebook
16 - Raw Input in the Notebook
17 - Rich Output
18 - Script Magics
19 - SymPy
20 - Terminal Usage
21 - Third Party Rich Output
22 - Trapezoid Rule
23 - Working With External Code

Beyond Python: magic functions

The IPython 'magic' functions are a set of commands, invoked by prepending one or two % signs to their name, that live in a namespace separate from your normal Python variables and provide a more command-like interface. They take flags with -- and arguments without quotes, parentheses or commas. The motivation behind this system is two-fold:

  • To provide an orthogonal namespace for controlling IPython itself and exposing other system-oriented functionality.

  • To expose a calling mode that requires minimal verbosity and typing while working interactively. Thus the inspiration taken from the classic Unix shell style for commands.


In [22]:
%magic

Line vs cell magics:


In [23]:
%timeit range(10)


The slowest run took 4.59 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 380 ns per loop

In [24]:
%%timeit
range(10)
range(100)


1000000 loops, best of 3: 752 ns per loop

Line magics can be used even inside code blocks:


In [26]:
for i in range(5):
    size = i*100
    print('size:',size)
    %timeit range(size)


size: 0
The slowest run took 7.58 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 239 ns per loop
size: 100
The slowest run took 4.42 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 390 ns per loop
size: 200
1000000 loops, best of 3: 394 ns per loop
size: 300
The slowest run took 5.56 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 430 ns per loop
size: 400
The slowest run took 4.68 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 410 ns per loop

Magics can do anything they want with their input, so it doesn't have to be valid Python:


In [27]:
%%bash
echo "My shell is:" $SHELL
echo "My memory status is:"
free


My shell is: /bin/bash
My memory status is:
             total       used       free     shared    buffers     cached
Mem:      12331664   10614648    1717016     279744     415172    4912048
-/+ buffers/cache:    5287428    7044236
Swap:      5116664     195104    4921560

Another interesting cell magic: create any file you want locally from the notebook:


In [28]:
%%writefile test.txt
This is a test file!
It can contain anything I want...

And more...


Writing test.txt

In [29]:
!cat test.txt


This is a test file!
It can contain anything I want...

And more...

Let's see what other magics are currently defined in the system:


In [30]:
%lsmagic


Out[30]:
Available line magics:
%alias  %alias_magic  %autocall  %automagic  %autosave  %bookmark  %cat  %cd  %clear  %colors  %config  %connect_info  %cp  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %install_default_config  %install_ext  %install_profiles  %killbgscripts  %ldir  %less  %lf  %lk  %ll  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %lx  %macro  %magic  %man  %matplotlib  %mkdir  %more  %mv  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %popd  %pprint  %precision  %profile  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %rm  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%latex  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.

Running normal Python code: execution and errors

Not only can you input normal Python code, you can even paste straight from a Python or IPython shell session:


In [32]:
>>> # Fibonacci series:
... # the sum of two elements defines the next
... a, b = 0, 1
>>> while b < 10:
...     print(b)
...     a, b = b, a+b


1
1
2
3
5
8

In [34]:
In [1]: for i in range(10):
   ...:     print(i)
   ...:


0
1
2
3
4
5
6
7
8
9

And when your code produces errors, you can control how they are displayed with the %xmode magic:


In [35]:
%%writefile mod.py

def f(x):
    return 1.0/(x-1)

def g(y):
    return f(y+1)


Writing mod.py

Now let's call the function g with an argument that would produce an error:


In [36]:
import mod
mod.g(0)


---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-36-a54c5799f57e> in <module>()
      1 import mod
----> 2 mod.g(0)

/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py in g(y)
      4 
      5 def g(y):
----> 6     return f(y+1)

/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py in f(x)
      1 
      2 def f(x):
----> 3     return 1.0/(x-1)
      4 
      5 def g(y):

ZeroDivisionError: float division by zero

In [37]:
%xmode plain
mod.g(0)


Exception reporting mode: Plain
Traceback (most recent call last):

  File "<ipython-input-37-8932f4bf53fa>", line 2, in <module>
    mod.g(0)

  File "/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py", line 6, in g
    return f(y+1)

  File "/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py", line 3, in f
    return 1.0/(x-1)

ZeroDivisionError: float division by zero

In [38]:
%xmode verbose
mod.g(0)


Exception reporting mode: Verbose
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-38-539f73e80e01> in <module>()
      1 get_ipython().magic('xmode verbose')
----> 2 mod.g(0)
        global mod.g = <function g at 0x7fac3c1fc620>

/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py in g(y=0)
      4 
      5 def g(y):
----> 6     return f(y+1)
        global f = <function f at 0x7fac3c1fc598>
        y = 0

/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py in f(x=1)
      1 
      2 def f(x):
----> 3     return 1.0/(x-1)
        x = 1
      4 
      5 def g(y):

ZeroDivisionError: float division by zero

The default %xmode is "context", which shows additional context but not all local variables. Let's restore that one for the rest of our session.


In [39]:
%xmode context


Exception reporting mode: Context

Running code in other languages with special %% magics


In [40]:
%%perl
@months = ("July", "August", "September");
print $months[0];


July

In [41]:
%%ruby
name = "world"
puts "Hello #{name.capitalize}!"


Hello World!

Exercise

Write a cell that executes in Bash and prints your current working directory as well as the date.

Apologies to Windows users who may not have Bash available, not sure how to obtain the equivalent result with cmd.exe or Powershell.


In [18]:
%load ../../exercises/soln/bash-script


Fri Apr  3 16:39:20 PDT 2015
My current directory is: /home/takluyver/Code/ipython-in-depth/examples/IPython Kernel

Raw Input in the notebook

Since 1.0 the IPython notebook web application support raw_input which for example allow us to invoke the %debug magic in the notebook:


In [42]:
mod.g(0)


---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-42-5e708f13c839> in <module>()
----> 1 mod.g(0)

/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py in g(y)
      4 
      5 def g(y):
----> 6     return f(y+1)

/home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py in f(x)
      1 
      2 def f(x):
----> 3     return 1.0/(x-1)
      4 
      5 def g(y):

ZeroDivisionError: float division by zero

In [43]:
%debug


> /home/takluyver/Code/ipython-in-depth/examples/IPython Kernel/mod.py(3)f()
      2 def f(x):
----> 3     return 1.0/(x-1)
      4 

ipdb> ll
  2  	def f(x):
  3  ->	    return 1.0/(x-1)
ipdb> x
1
ipdb> q

Don't foget to exit your debugging session. Raw input can of course be use to ask for user input:


In [46]:
enjoy = input('Are you enjoying this tutorial ?')
print('enjoy is :', enjoy)


Are you enjoying this tutorial ?yes
enjoy is : yes

Plotting in the notebook

This magic configures matplotlib to render its figures inline:


In [46]:
%matplotlib inline

In [47]:
import numpy as np
import matplotlib.pyplot as plt

In [48]:
x = np.linspace(0, 2*np.pi, 300)
y = np.sin(x**2)
plt.plot(x, y)
plt.title("A little chirp")
fig = plt.gcf()  # let's keep the figure object around for later...


The IPython kernel/client model


In [47]:
%connect_info


{
  "hb_port": 38047,
  "signature_scheme": "hmac-sha256",
  "control_port": 33215,
  "key": "f13a0040-c7df-481e-91aa-cf649757fbc9",
  "shell_port": 45816,
  "stdin_port": 48199,
  "iopub_port": 33110,
  "ip": "127.0.0.1",
  "transport": "tcp"
}

Paste the above JSON into a file, and connect with:
    $> ipython <app> --existing <file>
or, if you are local, you can connect with just:
    $> ipython <app> --existing kernel-f6538a5a-d46a-48e7-b6f2-ac2342ae155e.json 
or even just:
    $> ipython <app> --existing 
if this is the most recent IPython session you have started.

We can connect automatically a Qt Console to the currently running kernel with the %qtconsole magic, or by typing ipython console --existing <kernel-UUID> in any terminal:


In [48]:
%qtconsole